
#include "Engine.hpp"
#include "MyGame.hpp"

#include "SDLClock.hpp"
#include "SDLInput.hpp"
//#include "RakNetNetwork.hpp"
//#include "BigWorld.hpp"
#include "SDLRenderer.hpp"

#include <iostream> // For cout
using std::cout;
using std::endl;
#include <cstdlib> // For atoi
#include <cstring> // For strcmp
#include <memory> // For auto_ptr
using std::auto_ptr;
//typedef std::auto_ptr Ptr;
#ifdef WIN32
#include <windows.h>
#endif

#define MAX_CMD_LINE_ARGS 256

void printUsage()
{
	cout << "Usage: MyGame [options]" << endl;
	cout << endl;
	cout << "Options are:" << endl;
	cout << "  -f, --fullscreen        Enable fullscreen mode" << endl;
	cout << "  -r, --resolution w h    Set resolution to (w*h)" << endl;
	cout << "  -b, --bit-depth b       Set the bit-depth to b" << endl;
}

#ifdef WIN32
int WINAPI WinMain(	HINSTANCE	hInstance,			// Instance
					HINSTANCE	hPrevInstance,		// Previous Instance
					LPSTR		lpCmdLine,			// Command Line Parameters
					int			nCmdShow)			// Window Show State
#else
int main(int argc, char* argv[])
#endif
{
#ifdef WIN32
	// Convert WIN32 command line args to standard argc + argv
	// TODO: Check this for memory leaks
	int argc;
	char* argv[MAX_CMD_LINE_ARGS];
	char* token;
	argc = 1; // Skip first arg
	token = strtok(lpCmdLine, " ");
	while( token ) {
		argv[argc++] = token;
		token = strtok(NULL, " ");
	}
#endif
	
	bool fullscreen = false;
	int  width      = 800;
	int  height     = 600;
	int  bitdepth   = 0;
	
	// 'Simple' command-line parsing
	// TODO: Eventually replace this with tclap
	for( int i=1; i<argc; ++i ) {
		if( 0==strcmp(argv[i], "--fullscreen") ||
			0==strcmp(argv[i], "-f") ) {
			fullscreen = true;
			cout << "Setting fullscreen = true" << endl;
		}
		else if( 0==strcmp(argv[i], "--resolution") ||
				 0==strcmp(argv[i], "-r") ) {
			if( i+2 < argc ) {
				width = atoi(argv[++i]);
				height = atoi(argv[++i]);
				if( width<=0 || height<=0 )	{
					cout << "Error parsing param 'resolution'" << endl;
					printUsage();
					return -1;
				}
				cout << "Setting resolution = "
					 << width << "x" << height << endl;
			}
			else { printUsage(); return -1; }
		}
		else if( 0==strcmp(argv[i], "--bit-depth") ||
				 0==strcmp(argv[i], "-b") ) {
			if( i+1 < argc ) {
				bitdepth = atoi(argv[++i]);
				if( bitdepth<=0 )	{
					cout << "Error parsing param 'bitdepth'" << endl;
					printUsage();
					return -1;
				}
				cout << "Setting bitdepth = " << bitdepth << endl;
			}
			else { printUsage(); return -1; }
		}
	}
	
    // Create the engine and the game instance
	Engine* engine = new Engine();
	MyGame* game   = new MyGame(engine);
	
	// Create the engine components.
	// The engine will receive their events.
	IRenderer* renderer = new SDLRenderer(engine,
										  "MyGame window",
										  width, height,
										  bitdepth,
										  fullscreen);
	IClock*    clock    = new SDLClock();
	IInput*    input    = new SDLInput(engine);
	//INetwork*  network  = new RakNetNetwork(engine);
	// ...
	
	// Set the engine components
	engine->setClock(clock);
	engine->setInput(input);
	engine->setRenderer(renderer);
	//engine->setNetwork(network);
	// ...
	
	// Set the handlers for events from each of the engine components
	engine->setInputHandler(game);
	engine->setTickHandler(game);
	engine->setRendererHandler(game);
	//engine->setNetworkHandler(game);
	// ...
	
	// Set engine parameters
	// TODO: Check for errors if this is called prior to Engine::setClock()
	engine->setTickRate(60.0);
	
	// And start the engine!
	engine->start();
	
	// Clean up
	// ...
	//delete network;
	delete input;
	delete clock;
	delete renderer;
	delete game;
	delete engine;
	
	std::cout << "Done." << std::endl;
	return 0;
	
	/* TODO: Here's the same code using auto_ptr. (Ugly!)
    // Create the engine and the game instance
	auto_ptr<Engine> engine(new Engine());
	auto_ptr<MyGame> game(new MyGame( engine.get() ));
	
	// Create the engine components. The engine will receive their events.
	// Note: SDLRenderer must be created first! It initialises all of SDL!
	auto_ptr<IRenderer> renderer(new SDLRenderer( engine.get(), "MyGame window", 1024, 768, 0, false ));
	auto_ptr<IClock>    clock(new SDLClock( ));
	auto_ptr<IInput>    input(new SDLInput( engine.get() ));
	//Ptr<INetwork>       network(new RakNetNetwork( engine.get() ));
	//Ptr<IWorld>         world(new BigWorld( engine.get() ));
	
	// Set the engine components
	engine->setClock( clock.get() );
	engine->setInput( input.get() );
	engine->setRenderer( renderer.get() );
	//engine->setNetwork( network.get() );
	//engine->setPhysicsMgr( physics.get() );
	
	// Set the handlers for events from each of the engine components
	engine->setInputHandler( game.get() );
	engine->setTickHandler( game.get() );
	//engine->setNetworkHandler( game.get() );
	//engine->setPhysicsHandler( game.get() );
	engine->setRendererHandler( game.get() );
	
	// Set engine parameters
	engine->setTickRate(30.0);
	
	// And start the engine!
	engine->start();

	// Everything should be cleaned-up automatically
	cout << "Done.\n";
	return 0;
	*/
}
